package info.hexin.lang.reflect;

import info.hexin.json.Json;
import info.hexin.json.JsonConfig;
import info.hexin.lang.Exceptions;
import info.hexin.log.Log;
import info.hexin.log.Logs;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 反射包装类
 * 
 * @author hexin
 * 
 */
public abstract class Wrap {
    static Log log = Logs.get();

    /**
     * 修改Field的访问权限，如果为<code>public</code>不用修啊，如果不是修改成<code>public</code>
     * 
     * @param field
     */
    public static void setFieldPublicAccessible(Field field) {
        if (!Modifier.isPublic(field.getModifiers())) {
            field.setAccessible(true);
        }
    }

    /**
     * 将Map 和List 转化成Object
     * 
     * @param obj
     * @param t
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    @SuppressWarnings("unchecked")
    public static <T> T maplist2Object(Object listMapObject, Class<T> clazz) {
        try {
            if (clazz.isInterface()) {
                log.error("clazz  :" + clazz.getName() + "  is Interface,");
                return null;
            }
            T instance = clazz.newInstance();
            if (listMapObject.getClass() == ArrayList.class) {
                // List<Object> list = (List<Object>) listMapObject;
            } else {
                Map<String, Object> map = (HashMap<String, Object>) listMapObject;
                Field[] fields = instance.getClass().getDeclaredFields();
                for (Field field : fields) {
                    fieldAssignment(instance, field, map.get(field.getName()));
                }
            }
            return instance;
        } catch (InstantiationException e) {
            throw Exceptions.make(" java bean class is interface or abstra , is not newInstance !!");
        } catch (IllegalAccessException e) {
            throw Exceptions.make(" java bean class is not public  , is not newInstance !!");
        }

    }

    /**
     * 给fied赋值
     * 
     * @param instance
     * @param field
     * @param value
     */
    public static void fieldAssignment(Object instance, Field field, Object value) {
        try {
            if (value == null) {
                return;
            }
            setFieldPublicAccessible(field);
            Class<?> fieldClass = field.getType();
            log.info("instance class >>>> " + instance.getClass().getName() + ",fieldName >>> " + field.getName()
                    + ", fieldClass >>> " + fieldClass + ", value >>> " + value);
            if (fieldClass != value.getClass()) {
                if (String.class == fieldClass) {
                    field.set(instance, value.toString());
                } else if ("int".equals(fieldClass.toString()) || Integer.class == fieldClass) {
                    value = Integer.valueOf(value.toString());
                    field.set(instance, value);
                } else if ("long".equals(fieldClass.toString()) || Long.class == fieldClass) {
                    value = Long.valueOf(value.toString());
                    field.set(instance, value);
                } else if (fieldClass.isArray()) {
                    Object o = Json.fromJson(value.toString());
                    List<Object> tmpO = (List<Object>) o;
                    field.set(instance, tmpO.toArray(new String[0]));
                } else if (Date.class == fieldClass) {
                    value = JsonConfig.sdf.parse(value.toString());
                    field.set(instance, value);
                } else if ("boolean".equals(fieldClass.toString())) {
                    field.set(instance, Boolean.parseBoolean(value.toString()));
                } else if ("char".equals(fieldClass.toString())) {
                    String valueString = value.toString();
                    if (valueString.length() >= 1) {
                        field.set(instance, valueString.charAt(0));
                    }
                } else if ("double".equals(fieldClass.toString())) {
                    field.set(instance, Double.valueOf(value.toString()));
                } else if ("float".equals(fieldClass.toString())) {
                    field.set(instance, Float.valueOf(value.toString()));
                } else if ("byte".equals(fieldClass.toString())) {
                    field.set(instance, Byte.valueOf(value.toString()));
                } else if ("short".equals(fieldClass.toString())) {
                    field.set(instance, Short.valueOf(value.toString()));
                } else {
                    Object fieldInstance = maplist2Object(value, fieldClass);
                    field.set(instance, fieldInstance);
                }
            } else {
                field.set(instance, value);
            }
        } catch (Exception e) {
            throw Exceptions.make(e);
        }
    }
}
